#include "gtest/gtest.h"
#include "viml/compiler.h"
#include "viml/vm.h"
#include "viml/value.h"
#include <iostream>
#include <memory>

using namespace viml;

class ScopeFunctionTest : public ::testing::Test {
protected:
    Compiler compiler;
    VM vm;

    void execute_source(const std::string& source) {
        try {
            auto bytecode = compiler.compile(source, "<test>");
            vm.execute(bytecode);
        } catch (const std::exception& e) {
            FAIL() << "Execution failed: " << e.what();
        }
    }
};

// 测试函数参数作用域 (a:)
TEST_F(ScopeFunctionTest, FunctionArgumentScope) {
    std::string source = R"(
        function TestFunc(arg1, arg2)
            return a:arg1 + a:arg2
        endfunction
        
        let result = TestFunc(10, 20)
        echo result
    )";
    
    execute_source(source);
    EXPECT_TRUE(vm.has_global("result"));
    EXPECT_EQ(vm.get_global("result").as_number(), 30);
}

// 测试函数局部变量作用域 (l:)
TEST_F(ScopeFunctionTest, FunctionLocalScope) {
    std::string source = R"(
        function TestFunc(x)
            let l:local_var = a:x * 2
            return l:local_var
        endfunction
        
        let result = TestFunc(5)
        echo result
    )";
    
    execute_source(source);
    EXPECT_TRUE(vm.has_global("result"));
    EXPECT_EQ(vm.get_global("result").as_number(), 10);
}

// 测试函数作用域隔离
TEST_F(ScopeFunctionTest, FunctionScopeIsolation) {
    std::string source = R"(
        let g:global_var = 100
        
        function TestFunc()
            let l:local_var = 200
            return g:global_var + l:local_var
        endfunction
        
        let result = TestFunc()
        echo result
    )";
    
    execute_source(source);
    EXPECT_TRUE(vm.has_global("result"));
    EXPECT_EQ(vm.get_global("result").as_number(), 300);
}

// 测试嵌套函数调用的作用域
TEST_F(ScopeFunctionTest, NestedFunctionCalls) {
    std::string source = R"(
        function Outer(x)
            function Inner(y)
                return a:y * 2
            endfunction
            return Inner(a:x) + 10
        endfunction
        
        let result = Outer(5)
        echo result
    )";
    
    execute_source(source);
    EXPECT_TRUE(vm.has_global("result"));
    EXPECT_EQ(vm.get_global("result").as_number(), 20);
}

// 测试递归函数的作用域独立性
TEST_F(ScopeFunctionTest, RecursiveFunctionScope) {
    std::string source = R"(
        function Factorial(n)
            if a:n <= 1
                return 1
            else
                return a:n * Factorial(a:n - 1)
            endif
        endfunction
        
        let result = Factorial(5)
        echo result
    )";
    
    execute_source(source);
    EXPECT_TRUE(vm.has_global("result"));
    EXPECT_EQ(vm.get_global("result").as_number(), 120);
}

// 测试函数内无前缀变量的兼容性（应使用全局作用域）
TEST_F(ScopeFunctionTest, FunctionImplicitGlobalCompatibility) {
    std::string source = R"(let global_var = 42

function TestFunc()
    return global_var
endfunction

let result = TestFunc()
echo result)";
    
    execute_source(source);
    EXPECT_TRUE(vm.has_global("result"));
    EXPECT_EQ(vm.get_global("result").as_number(), 42);
}

// 测试函数参数和局部变量的隔离
TEST_F(ScopeFunctionTest, FunctionParameterLocalIsolation) {
    std::string source = R"(function TestFunc(param)
    let l:param = a:param * 2
    return l:param
endfunction

let result = TestFunc(10)
echo result)";
    
    execute_source(source);
    EXPECT_TRUE(vm.has_global("result"));
    EXPECT_EQ(vm.get_global("result").as_number(), 20);
}

int main(int argc, char **argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}